
#include <head.h>
//#include <stdio.h>
//#include <unistd.h>
#include <signal.h>

#include <iostream>

#include <workflow/WFFacilities.h>
#include <workflow/WFHttpServer.h>
#include <workflow/WFTaskFactory.h>
#include <workflow/HttpUtil.h>
#include <workflow/HttpMessage.h>
#include <workflow/RedisMessage.h>

using std::cout;
using std::endl;
using std::string;
using std::vector;

//初始化计数器的值为1
static WFFacilities::WaitGroup waitGroup(1);

struct SeriesContext
{
    string password;
    protocol::HttpResponse * resp;
};

void sighandler(int num)
{
    printf(">> sig num %d is comming\n", num);
    //调用一次done方法，计数器的值减1
    waitGroup.done();
}

void redisCallback(WFRedisTask * redistask)
{
    //0. 对任务的状态和错误进行检测
    //1. 获取序列的共享数据
    //获取serverTask中的password;
    //获取serverTask中的resp
    SeriesContext * pContext = (SeriesContext*)series_of(redistask)->get_context();
    //2. 获取响应信息
    protocol::RedisValue result;
    auto redisResp = redistask->get_resp();
    redisResp->get_result(result);
    if(result.is_string()) {
        string passwd = result.string_value();
        //与serverTask中解析出来的password进行对比
        if(pContext->password == passwd) {
            //验证通过的情况
            pContext->resp->append_output_body("Login Success!");
        } else {//验证失败的情况
            pContext->resp->append_output_body("Login Failed!");
        }
    } else {
        //不是字符串形式时，一定出错，生成响应信息
        pContext->resp->append_output_body("Login Failed!");
    }
}

void serverCallback(WFHttpTask * serverTask)
{
    printf("serverCallback is running.\n");
    //注意：当执行该serverCallback时，resp已经发送给对端了
    int state = serverTask->get_state();
    int error = serverTask->get_error();

    printf("state: %d, error: %d\n\n\n", state, error);
}

void process(WFHttpTask * serverTask)
{
    //只要执行process函数，一定接收到了对端的请求数据
    printf("process is running.\n");
    //0. 对任务的状态进行检测
    //0.1设置serverTask的回调函数
    serverTask->set_callback(serverCallback);
    //1. 解析请求
    auto req = serverTask->get_req();
    string uri = req->get_request_uri();
    cout << "uri: " << uri << endl;
    string method = req->get_method();
    cout << "method: " << method << endl;

    if(method == "GET" && uri == "/postform.html") {
        //读取服务器本地的postform.html
        string filename("postform.html");
        int fd = open(filename.c_str(), O_RDONLY);
        if(fd < 0) {
            perror("open");
            return;
        }
        char buff[1024] = {0};
        //读取postform.html文件的内容
        int ret = read(fd, buff, sizeof(buff));
        //生成响应信息
        serverTask->get_resp()->add_header_pair("Content-Type", "text/html");
        serverTask->get_resp()->append_output_body(buff, ret);

        //关闭打开的文件的fd
        close(fd);
    } else if(method == "POST" && uri == "/postform.html"){
        //获取请求的消息体
        const void * body = nullptr;
        size_t sz = 0;
        serverTask->get_req()->get_parsed_body(&body, &sz);
        string strBody((const char*)body, sz);
        cout << "strBody: " << strBody << endl;

        //解析用户名和密码
        string usernameKV = strBody.substr(0, strBody.find("&"));
        string passwordKV = strBody.substr(strBody.find("&") + 1);
        string username = usernameKV.substr(usernameKV.find("=") + 1);
        string password = passwordKV.substr(passwordKV.find("=") + 1);
        cout << "username: " << username << endl;
        cout << "password: " << password << endl;

        //在序列中设置共享数据
        auto pContext = new SeriesContext();
        pContext->password = password;
        pContext->resp = serverTask->get_resp();
        series_of(serverTask)->set_context(pContext);
        series_of(serverTask)->set_callback(
        [pContext](const SeriesWork * ){
            //在序列的回调函数中，回收context数据            
            if(pContext) {
                delete pContext;
                cout << "SeriesContext has been free\n\n";
            }
        });

        //2. 访问Redis，并进行验证
        string url = "redis://127.0.0.1:6379";
        auto redisTask = WFTaskFactory::create_redis_task(url, 1, redisCallback); 
        string command("HGET");
        vector<string> params {"student", username};
        redisTask->get_req()->set_request(command, params);
        series_of(serverTask)->push_back(redisTask);
    }
}

void test0()
{
    signal(SIGINT, sighandler);

    WFHttpServer httpServer(process);

    if(httpServer.start(8888) == 0) {
        //当调用wait方法会阻塞当前线程
        waitGroup.wait();
        httpServer.stop();
    } else {
        printf("Http Server start failed.\n");
    }
    cout << "\n>> test0 exit" << endl;
}


int main()
{
    test0();
    return 0;
}

